﻿using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sovacode.RubiksCube.Common.Collections;
using Sovacode.RubiksCube.Common.Exceptions;
using Sovacode.RubiksCube.Common.Model;

namespace Sovacode.RubiksCube.Common.Tests.Collections
{
    [TestClass]
    public class CommonAdvancedCollectionTests
    {
        [TestMethod]
        public void CreateCollection()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            Assert.IsNotNull(collection);

            Assert.IsTrue(collection.Count == 0);

        }

        [TestMethod]
        public void CreateCollectionWithList()
        {
            var list = new List<DataObject>
                           {
                               new DataObject {Name = "A1"},
                               new DataObject {Name = "A2"},
                               new DataObject {Name = "A3"},
                               new DataObject {Name = "A4"}
                           };

            var collection = new AdvancedObservableCollection<DataObject>(list);

            Assert.IsNotNull(collection);
            Assert.IsTrue(collection.Count == 4);
        }

        [TestMethod]
        public void Add()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            collection.Add(new DataObject());

            Assert.IsTrue(collection.Count == 1);
        }

        [TestMethod]
        public void Remove()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            var data = new DataObject();

            collection.Add(data);

            collection.Remove(data);

            Assert.IsTrue(collection.Count == 0);
        }

        [TestMethod]
        public void AddRange()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            var list = new List<DataObject> {new DataObject(), new DataObject(), new DataObject()};

            collection.AddRange(list);

            Assert.IsTrue(collection.Count == 3);
        }

        [TestMethod]
        public void AddEmptyRange()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            collection.AddRange(null);

            Assert.IsTrue(collection.Count == 0);
        }

        [TestMethod]
        public void HasIndex()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            var list = new List<DataObject> { new DataObject(), new DataObject(), new DataObject() };

            collection.AddRange(list);

            Assert.IsTrue(collection.HasIndex(0));
            Assert.IsTrue(collection.HasIndex(1));
            Assert.IsTrue(collection.HasIndex(2));
            Assert.IsFalse(collection.HasIndex(3));

            Assert.IsFalse(collection.HasIndex(-1));
            Assert.IsFalse(collection.HasIndex(-2));
            Assert.IsFalse(collection.HasIndex(-3));
        }

        [TestMethod]
        public void HasIndexEmptyCollection()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            Assert.IsFalse(collection.HasIndex(0));
            Assert.IsFalse(collection.HasIndex(1));
            Assert.IsFalse(collection.HasIndex(2));
            Assert.IsFalse(collection.HasIndex(3));

            Assert.IsFalse(collection.HasIndex(-1));
            Assert.IsFalse(collection.HasIndex(-2));
            Assert.IsFalse(collection.HasIndex(-3));
        }

        [TestMethod]
        public void AddNull()
        {
            Assert.IsTrue(new AdvancedObservableCollection<DataObject> {null}.Count == 1);
        }

        [TestMethod]
        public void AddNulls()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            collection.AddRange(new List<DataObject>
                                    {
                                        new DataObject(),
                                        null,
                                        new DataObject()
                                    });

            Assert.IsTrue(collection.Count == 3);
        }

        [TestMethod]
        [ExpectedException(typeof(NullsNotAllowedException))]
        public void AddNullNotAllowed()
        {
            new AdvancedObservableCollection<DataObject> { AllowNulls = false }.Add(null);
        }

        [TestMethod]
        [ExpectedException(typeof(NullsNotAllowedException))]
        public void AddNullsNotAllowed()
        {
            new AdvancedObservableCollection<DataObject> {AllowNulls = false}.AddRange(new List<DataObject> { new DataObject(), null, new DataObject() });
        }

        [TestMethod]
        public void MustExposes()
        {
            var collection = new AdvancedObservableCollection<DataObject>();

            Assert.IsInstanceOfType(collection, typeof(INotifyPropertyChanged));
            Assert.IsInstanceOfType(collection, typeof(ICollection));
            Assert.IsInstanceOfType(collection, typeof(IList));
        }
    }
}
